using System;
using System.Collections.Generic;
using CQRS.General;

namespace CQRS.Events
{
    public class Bus<TMessage> : IBus<TMessage> where TMessage : class, new()
    {
        private readonly object _lockObject = new object();
        private readonly IMessageRouter _messageRouter;
        private readonly Queue<TMessage> _preCommitQueue;

        public Bus(IMessageRouter messageRouter)
        {
            _messageRouter = messageRouter;
            _preCommitQueue = new Queue<TMessage>(32);
        }

        #region IBus<TMessage> Members

        public void Publish(TMessage message)
        {
            lock (_lockObject)
            {
                _preCommitQueue.Enqueue(message);
            }
        }

        public void Publish(IEnumerable<TMessage> messages)
        {
            lock (_lockObject)
            {
                foreach (TMessage message in messages)
                {
                    _preCommitQueue.Enqueue(message);
                }
            }
        }

        public void Commit()
        {
            lock (_lockObject)
            {
                while (_preCommitQueue.Count > 0)
                {
                    DoPublish(_preCommitQueue.Dequeue());
                }
            }
        }

        public void Rollback()
        {
            lock (_lockObject)
            {
                _preCommitQueue.Clear();
            }
        }

        #endregion

        private void DoPublish(TMessage message)
        {
            try
            {
                _messageRouter.Route(message);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
        }
    }
}